package service.demo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class ServiceActivity extends Activity {
	
    /**
     * Service 分为两种启动模式：
     * 1. context.startService() 模式
     * 			这种模式下Service的调用者与Service本事无直接联系，即使调用者的生命周期结束。service仍然会继续运行
     * 			startService() 来实例化service：startService()调用后-> onCreate() -> onStartCommand()  -> onStart() 方法被依次调用。
     * 			stopService() 来终止service：stopService()调用后 ->onDestroy()  方法被依次调用。
	 * 2. context.bindService() 模式
	 * 			Service调用者与Service绑定在一起，调用者生命周期结束的同时Service也立即终止。
	 * 			bindService() 绑定service：	
	 * 				bindService()调用后下面的方法依次被调用
	 * 					-> onCreate() 
	 * 						-> onBind() 
	 * 							-> onServiceConnected()：当这个方法被调用是表示绑定成功
	 * 
	 * 			unbindService() 解除绑定service：
	 * 				unbindService() 调用后下面的方法依次被调用
	 * 					-> onUnBind() 
	 * 						-> onDestroy()：Service生命周期结束
	 * 			
	 * 			实现绑定注意一下两点：
	 * 
	 * 			1. 在使用bindService绑定服务时，我们需要一个ServiceConnection代表与服务的连接，它只有两个方法，onServiceConnected
	 * 				和onServiceDisconnected，前者是在操作者在连接一个服务成功时被调用，而后者是在服务崩溃或被杀死导致的连接中断时被
	 * 				调用，而如果我们自己解除绑定时则不会被调用，所以我们这里只研究onServiceConnected这个方法。 
	 * 			
	 * 			2. 要想实现绑定操作，必须返回一个实现了IBinder接口类型的实例，该接口描述了与远程对象进行交互的抽象协议，有了它我们才
	 * 				能与服务进行交互。我们于是有了这样的代码：
	 * 
	 *  这两种模式都是再第一次创建创建一个Service实例 除非Service被Destroy否则系统不会创建新实例。
	 *  
	 *  使用service步骤：
	 *  1. 继承service类 并且复写其中的方法 (看ServiceEntity.java类)
	 *  2. 在AndroidManifest.xml 注册service
	 *  3. 调用 startService() / stopService() 实例化 / 终止一个service
	 *  			bindService() /	unbindService() 绑定 / 解绑 一个service	
	 *  
	 *  需要注意的：是如果一个Service本身为连接中断状态，此时调用unbindService系统会抛出异常。为避免这类情况的发生我们可以在
	 *  onServiceConnected() 方法中设置一个标志（isConnected = true） 然后在调用unbindService()方法前判断该变量，等于true则执行。
	 *  
     * 实验：
     * 如果我们先以startService方式启动服务，然后再用bindService绑定到这个服务，之后使用unbindService解除绑定，此时服务并不会因
     * 此而终止，而是继续运行，直到我们使用stopService来停止这个服务。
     * 
     * 依次点击 Start Service -> Bind Service -> Unbind Service -> Stop Service 按钮观察Log，当点击Unbind Service按钮时Service无法停止。
     * 必须要点击Stop Service 按钮才能终止Service。
     * 
     * 进程内与服务通信
     * 进程内与服务通信实际上就是通过bindService的方式与服务绑定，获取到通信中介Binder实例，然后通过调用这个实例的方法，完成对服务的
     * 各种操作。
     * 	1. 自定义的Binder类和方法(BinderEntity 内部类)。
     *	2. 在ServiceEntity类的onBind() 方法中返回一个自定义BinderEntity实例.
     *	3. 在onServiceConnected()方法中将IBinder service 强制转换为BinderEntity实例，至此我们可以访问自定义的Binder类中的成员和成员方法。
     */
	
	Button btnStartService = null;
	Button btnStopService = null;
	
	Button btnBindService = null;
	Button btnUnbindService = null;
	
	boolean isConnected = false;

	ServiceConnection conn = new ServiceConnection() {

    	//连接一个服务成功时此方法被调用
		public void onServiceConnected(ComponentName name, IBinder service) {
			isConnected = true;
			Log.v("ServiceEntity", "ServiceEntity -> onServiceConnected()");
		}

		//服务崩溃或被杀死导致的连接中断时被调用
		public void onServiceDisconnected(ComponentName name) {
			Log.v("ServiceEntity", "ServiceEntity -> onServiceDisconnected()");
		}  
    }; 
    
	 //进程内与服务通信
    Button btnProcessCommunicateWithService = null;
    ServiceEntity.BinderEntity binderEntity = null;

    ServiceConnection connection = new ServiceConnection() {
    	//连接一个服务成功时此方法被调用
		public void onServiceConnected(ComponentName name, IBinder service) {
			isConnected = true;
		    
			//3. 在onServiceConnected()方法中将IBinder service 强制转换为BinderEntity实例，至此我们可以访问自定义的Binder类中的成员和成员方法。
			binderEntity = (ServiceEntity.BinderEntity) service;
			binderEntity.printName("My name is emma");
		}

		//服务崩溃或被杀死导致的连接中断时被调用
		public void onServiceDisconnected(ComponentName name) {
			Log.v("ServiceEntity", "ServiceEntity -> onServiceDisconnected()");
		}  
    }; 
    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        btnStartService = (Button)this.findViewById(R.id.btnStartService);
        btnStopService = (Button)this.findViewById(R.id.btnStopService);
        
        btnBindService = (Button)this.findViewById(R.id.btnBindService);
        btnUnbindService = (Button)this.findViewById(R.id.btnUnbindService);
        
        btnProcessCommunicateWithService = (Button)this.findViewById(R.id.btnProcessCommunicateWithService);
        
        //context.startService 模式
        btnStartService.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				Intent intent = new Intent(ServiceActivity.this, ServiceEntity.class);
				startService(intent);
			}
		});
        
        btnStopService.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				Intent intent = new Intent(ServiceActivity.this, ServiceEntity.class);
				stopService(intent);
			}
		});
        
        //context.bindService() 模式
        btnBindService.setOnClickListener(new View.OnClickListener() {
			
     			public void onClick(View v) {
     				Intent intent = new Intent(ServiceActivity.this, ServiceEntity.class);  
     			    bindService(intent, conn, Context.BIND_AUTO_CREATE); 
     			}
        });
        
        btnUnbindService.setOnClickListener(new View.OnClickListener() {
			
     			public void onClick(View v) {
     				if (isConnected) {
	     				unbindService(conn);
	     				isConnected = false;
     				}
     			}
        });
        
        //进程内与服务通信
        btnProcessCommunicateWithService.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				//绑定Service 注意这里使用的是 connection 不是 conn 对象
				Intent intent = new Intent(ServiceActivity.this, ServiceEntity.class);  
 			    bindService(intent, connection, Context.BIND_AUTO_CREATE); 
 			    
 			    try {
 			    	Thread.sleep(3000);
 			    } catch (Exception ex) {
 			    	
 			    }
 			    
 			    //接触绑定
 			   if (isConnected) {
    				unbindService(connection);
    				isConnected = false;
				}
			}
		});
    }
}